//
//  ServiceBase.m
//  Protocol
//
//  Created by  user on 11-1-13.
//  Copyright 2011 GuangZhouXuanWu. All rights reserved.
//

#import "GWService.h"

#import "SocketChannel.h"
#import "XMSHttpChannel.h"

#import "ProtocolBase.h"
#import "ProtocolStream.h"
#import "ProtocolHTTPSREST.h"
#import "SocketChannel.h"
#import "RequestChannelPoolShell.h"
#import "ErrorCode.h"

#import "XLGSessionOutInternal.h"

#import "GWService+GWServiceIPPort.h"

#import "XLGProtocolRequestAddress.h"

static NSUInteger s_networkActivityIndicatorVisibleCount = 0;

@interface CGWService (Private)<CSocketChannelDelegate,XMSHttpChannelDelegate>

- (int)QueryService2:(CProtocolStream *)request output:(CProtocolStream *)response;

- (void)stopQueryWaiting;

@end

@implementation CGWService
{
	int _nResult;
    NSError *_error;
    BOOL _bRequesting;
    
    CSocketChannel* _sc;
    XMSHttpChannel *_httpchannel;

    __unsafe_unretained id<CGWServiceDelegate> _delegate;
}

//@synthesize m_senddelegate;
@synthesize requesting = _requesting;

@synthesize delegate = _delegate;

- (void)dealloc
{
    [_error release_mm];
    [_httpchannel release_mm];
    [_sc release_mm];
    superdealloc_mm;
}

//- (void)terminateService
//{
//    m_sc.m_bSrun = FALSE;
//    m_sc.m_bRrun = FALSE;
//}

- (void)setSendTimeout:(NSTimeInterval)sendTimeout
{
    _sc.sendTimeout = sendTimeout;
}

- (void)setRecvTimeout:(NSTimeInterval)recvTimeout
{
    _sc.recvTimeout = recvTimeout;
}

- (NSTimeInterval)m_nSendtimeout
{
    return _sc.sendTimeout;
}

- (NSTimeInterval)m_nRecvtimeout
{
    return _sc.recvTimeout;
}

#pragma mark --

- (id)init
{
    self = [super init];
    
    return self;
}

- (id)initWithSocketChannel:(NSString *)szIP port:(int)nPort
{
    self = [self init];
    
    _sc = [[CSocketChannel alloc] initWithIP:szIP port:nPort];
    
    return self;
}

- (int)Query2:(CProtocolBase *)protocol output:(NSObject **)obj protocolerror:(NSError **)error
{
    @autoreleasepool
    {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
        
        int nResult = 0;
        
        CProtocolStream *request = [[CProtocolStream new]autorelease_mm];
        CProtocolStream *response = [[CProtocolStream new]autorelease_mm];
        
        [protocol write:request];
        
        nResult = [self QueryService2:request output:response];
        
        if (TRUE == nResult)
        {
            [protocol read:response output:obj];
            if (protocol.nErrorcode != YES)
            {
                if (-25013 == protocol.nErrorcode && [CSessionOutInternal responseSessionOut] == YES)
                {
                    nResult = TERMINATEREADWRITE;
                }
                else
                {
                    if (error != nil)
                        (*error) = [[NSError alloc] initWithDomain:protocol.szErrormsg code:protocol.nErrorcode userInfo:nil];
                    nResult = PROTOCOLRETOBJNIL;
                }
            }
        }
        
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        
        return nResult;
    }
}

- (int)QueryService2:(CProtocolStream *)request output:(CProtocolStream *)response
{
    _nResult = TERMINATEREADWRITE;

    _sc.delegate = self;
    _sc.request = request;
    _sc.response = response;

    _bRequesting = YES;

    int nResult = [CRequestChannelPoolShell addRequestChannel:^CRequestChannel *
    {
        return _sc;
    }];

    if(nResult == YES)
        nResult = [_sc initSocketChannel];
    
    if (YES == nResult)
    {
        if([_sc beginRequest])
        [_sc waitingFinish];
    }

    [CRequestChannelPoolShell removeRequestChannel:^CRequestChannel *
    {
        return _sc;
    }];
    [_sc closeSocket];

    _bRequesting = NO;

    _sc.request = nil;
    _sc.response = nil;
    [_sc release_mm];
    _sc = nil;

    return _nResult;
}

- (void)socketOperateResult:(CSocketChannel *)sc type:(ESocketOperateResultType)type result:(int)nResult
{
    switch ((int) type)
    {
        case ESocketOperateResultTypeError:
        case ESocketOperateResultTypeWriteTimeout:
        case ESocketOperateResultTypeReadTimeout:
        case ESocketOperateResultTypeFinish:
        case ESocketOperateResultTypeConnectTimeout:
        {
            _sc.delegate = nil;
            _nResult = nResult;
            [sc stopWaiting];

            break;
        }
    }
}

- (void)stopQueryWaiting
{
    if(_sc != nil)
        [_sc stopWaiting];
    else if(_httpchannel != nil)
        [_httpchannel stopWaiting];
}

- (BOOL)terminateService
{
    if(_sc != nil)
    {
        [CRequestChannelPoolShell cancelRequestChannel:_sc];
    }
    else if(_httpchannel != nil)
    {
        [CRequestChannelPoolShell cancelRequestChannel:_httpchannel];
    }
    
    return YES;
}

#pragma  mark --------------new----------------

- (XLGResult*)sendHTTPProtocol:(CProtocolBase *)protocol requestAddress:(XLGProtocolRequestAddress*)address
{
    XLGResult *result = nil;
    
    @autoreleasepool
    {
        NSInteger nResult = 0;
        NSObject *outObj = nil;
        NSError *outError = nil;
        
        CProtocolHTTPSREST *request = [CProtocolHTTPSREST protocolHTTSRESTWithRequestHead];
        CProtocolHTTPSREST *response = [[CProtocolHTTPSREST new]autorelease_mm];
        
        [protocol writeHTTPSREEST:request];
        
        nResult = [self sendHTTPRequest:request requestAddress:address output:response];
        
//        if (TRUE == nResult)
//        {
//            [protocol readHTTPSREEST:response output:obj];
//            if (protocol.nErrorcode != 0)
//            {
//                if (-25013 == protocol.nErrorcode && [CSessionOutInternal responseSessionOut] == YES)
//                {
//                    nResult = TERMINATEREADWRITE;
//                }
//                else
//                {
//                    if (error != nil)
//                        (*error) = [[NSError alloc] initWithDomain:protocol.szErrormsg code:protocol.nErrorcode userInfo:nil];
//                    nResult = PROTOCOLRETOBJNIL;
//                }
//            }
//        }
//        else
//        {
//        }
        
        switch(nResult)
        {
            case YES:
            {
                if(response.body.length > 0 )
                {
                    [protocol readHTTPSREEST:response output:&outObj];
                    if (protocol.nErrorcode == 0)
                    {
                        if (-25013 == protocol.nErrorcode && [CSessionOutInternal responseSessionOut] == YES)
                        {
                            nResult = TERMINATEREADWRITE;
                        }
                        else
                        {
                            outError = [[[NSError alloc] initWithDomain:protocol.szErrormsg code:protocol.nErrorcode userInfo:nil] autorelease_mm];
                            nResult = PROTOCOLRETOBJNIL;
                        }
                    }
                }
                else
                    nResult = NO;
                break;
            }
            case 401:
            {
                if ([CSessionOutInternal responseSessionOut] == YES)
                {
                    nResult = TERMINATEREADWRITE;
                }
                break;
            }
        }
        
        result = [[XLGResult resultWithOutResult:nResult outObj:outObj outError:outError] retain_mm];
    }
    
    return [result autorelease_mm];
}

- (int)sendHTTPRequest:(CProtocolHTTPSREST *)request requestAddress:(XLGProtocolRequestAddress*)address output:(CProtocolHTTPSREST *)response
{
    BOOL bResult = FALSE;
    __block XMSHttpChannel *http = nil;
    NSString *url=[NSString stringWithFormat:@"%@/%@",address.website,request.URI];
    bResult = [CRequestChannelPoolShell addRequestChannel:^CRequestChannel *
    {
        http = [[XMSHttpChannel alloc]initWithURLString:url];
        http.delegate=self;
        [http setHTTPHeaderFields:request.requestHead];
        switch((int)request.HTTPRESTMethod)
        {
            case EHTTPRESTMethodGet:
            {
                [http setHTTPGetMethod];
                break;
            }
            case EHTTPRESTMethodPost:
            {
                [http setHTTPPostMethod];
                break;
            }
            case EHTTPRESTMethodPut:
            {
                [http setHTTPPutMethod];
                break;
            }
            case EHTTPRESTMethodDelete:
            {
                [http setHTTPDeleteMethod];
            }
        }
        [http setHTTPDataBody:request.body];
        return http;
    }];
    
    if(bResult == YES)
    {
        _httpchannel = http;
        
        if([http startRequest])
        {
            [http waitingFinish];
            
            if(_nResult == YES)
                response.body = _httpchannel.data;
        }
    }
    
    [CRequestChannelPoolShell removeRequestChannel:^CRequestChannel *
    {
        _httpchannel = nil;
        return [http autorelease_mm];
    }];

    return _nResult;
}

-(void)HTTPOperateResult:(XMSHttpChannel *)http type:(XMSHTTPOperateResultType)type result:(int)nResult error:(NSError *)error
{
    switch((int)type)
    {
        case XMSHTTPOperateResultTypeFinish:
        {
            http.delegate = nil;
            _nResult=nResult;
            [http stopWaiting];
            break;
        }
        case XMSHTTPOperateResultTypeTerminate:
        {
            http.delegate = nil;
            _nResult=TERMINATEREADWRITE;
            ReleaseObj(_error);
            _error = [error retain_mm];
            [http stopWaiting];
            break;
        }
        default:
        {
            http.delegate = nil;
            _nResult=nResult;
            ReleaseObj(_error);
            _error = [error retain_mm];
            [http stopWaiting];
            break;
        }
    }
}

- (XLGResult*)sendSocketStreamProtocol:(CProtocolBase *)protocol requestAddress:(XLGProtocolRequestAddress*)address
{
    XLGResult *result = nil;
    @autoreleasepool
    {
        NSInteger nResult = 0;
        NSObject *outObj = nil;
        NSError *outError = nil;
        
        CProtocolStream *request = [[CProtocolStream new]autorelease_mm];
        CProtocolStream *response = [[CProtocolStream new]autorelease_mm];
        
        [protocol write:request];
        
        nResult = [self sendSocketRequestStream:request requestAddress:address output:response];
        
        if (TRUE == nResult)
        {
            [protocol read:response output:&outObj];
            if (protocol.nErrorcode != 0)
            {
                if (-25013 == protocol.nErrorcode && [CSessionOutInternal responseSessionOut] == YES)
                {
                    nResult = TERMINATEREADWRITE;
                }
                else
                {
                    outError = [[[NSError alloc] initWithDomain:protocol.szErrormsg code:protocol.nErrorcode userInfo:nil] autorelease_mm];
                    nResult = PROTOCOLRETOBJNIL;
                }
            }
        }
        result = [XLGResult resultWithOutResult:nResult outObj:outObj outError:outError];
    }
    
    return result;
}

- (int)sendSocketRequestStream:(CProtocolStream *)request requestAddress:(XLGProtocolRequestAddress*)address output:(CProtocolStream *)response
{
    _nResult = TERMINATEREADWRITE;
    _bRequesting = YES;
    
    __block CSocketChannel *sc = nil;
    int nResult = [CRequestChannelPoolShell addRequestChannel:^CRequestChannel *
    {
        sc = [[CSocketChannel alloc]initWithIP:address.ip port:address.port];
        sc.delegate = self;
        sc.request = request;
        sc.response = response;
        return sc;
    }];
    
    if(nResult == YES)
    {
        _sc = sc;
        nResult = [_sc initSocketChannel];
    }
    
    if (YES == nResult)
    {
        if([_sc beginRequest])
        [sc waitingFinish];
    }
    
    [CRequestChannelPoolShell removeRequestChannel:^CRequestChannel *
    {
        _sc = nil;
        sc.request = nil;
        sc.response = nil;
        [sc closeSocket];
        return [sc autorelease_mm];
    }];
    
    _bRequesting = NO;
    
    return _nResult;
}

-(XLGResult*)sendProtocol:(CProtocolBase*)protocol
{
    @synchronized(@"networkActivityIndicatorVisible")
    {
        if(s_networkActivityIndicatorVisibleCount == 0)
            [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
        s_networkActivityIndicatorVisibleCount ++;
    }
    
    XLGResult *result = nil;
    XLGProtocolRequestAddress *address=[self getGWServiceProtocol:protocol];
    switch((int)protocol.transformType)
    {
        case EProtocolTransformTypeHTTPSREST:
        case EProtocolTransformTypeHTTPSRESTFORFILE:
        {
            result = [self sendHTTPProtocol:protocol requestAddress:address];
            break;
        }
        case EProtocolTransformTypeSocketStream:
        {
            result = [self sendSocketStreamProtocol:protocol requestAddress:address];
            break;
        }
    }
    
    @synchronized(@"networkActivityIndicatorVisible")
    {
        s_networkActivityIndicatorVisibleCount --;
        if(s_networkActivityIndicatorVisibleCount == 0)
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    }
    
    return result;
}

-(NSInteger)sendProtocol:(CProtocolBase*)protocol recvOutput:(NSObject**)output protocolError:(NSError**)error
{
    XLGResult *result = [self sendProtocol:protocol];
    
    *output = [result.outObj retain_mm];
    *error = [result.outError retain_mm];
    
    return result.outResult;
}

-(NSInteger)createLongConnectSocketChannel:(NSString*)szIP port:(int)port
{
    NSInteger nResult = FALSE;
    if(_sc == nil)
    {
        _sc = [[CSocketChannel alloc]initWithIP:szIP port:port];
        nResult = [CRequestChannelPoolShell addRequestChannel:^CRequestChannel *
        {
            return _sc;
        }];
        
        if(nResult==YES)
        {
            nResult = [_sc initLongConnectSocketChannel];
        }
    }
    return nResult;
}

-(void)closeLongConnectSocketChannel
{
    [CRequestChannelPoolShell removeRequestChannel:^CRequestChannel *
    {
        [_sc closeSocket];
        
        CSocketChannel *sc = [[_sc retain_mm]autorelease_mm];
        
        ReleaseObj(_sc);
        
        return sc;
    }];
}

-(XLGResult*)longConnectSendProtocol:(CProtocolBase *)protocol
{
    @synchronized(@"networkActivityIndicatorVisible")
    {
        if(s_networkActivityIndicatorVisibleCount == 0)
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
        s_networkActivityIndicatorVisibleCount ++;
    }
    
    XLGResult *result = nil;
    
    @autoreleasepool
    {
        _nResult = 0;
        NSObject *outObj = nil;
        NSError *outError = nil;
        
        CProtocolStream *request = [[CProtocolStream new]autorelease_mm];
        CProtocolStream *response = [[CProtocolStream new]autorelease_mm];
        
        [protocol write:request];
        
        _sc.request=request;
        _sc.response=response;
        
        _sc.delegate = self;
        if([_sc beginRequest])
            [_sc waitingFinish];
        
        [_sc endRequest];
        
        _sc.request=nil;
        _sc.response=nil;

        if (TRUE == _nResult)
        {
            [protocol read:response output:&outObj];
            if (protocol.nErrorcode != 0)
            {
                if (-25013 == protocol.nErrorcode && [CSessionOutInternal responseSessionOut] == YES)
                {
                    _nResult = TERMINATEREADWRITE;
                }
                else
                {
                    outError = [[[NSError alloc] initWithDomain:protocol.szErrormsg code:protocol.nErrorcode userInfo:nil] autorelease_mm];
                    _nResult = PROTOCOLRETOBJNIL;
                }
            }
        }
        
        result = [XLGResult resultWithOutResult:_nResult outObj:outObj outError:outError];
    }
    
    @synchronized(@"networkActivityIndicatorVisible")
    {
        s_networkActivityIndicatorVisibleCount --;
        if(s_networkActivityIndicatorVisibleCount == 0)
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    }
    
    return result;
}

-(void)socketChannel:(CSocketChannel *)sc willSendTotalBytes:(NSUInteger)bytes
{
    if([_delegate respondsToSelector:@selector(GWService:willSendTotalBytes:)])
       [_delegate GWService:self willSendTotalBytes:bytes];
}

-(void)socketChannel:(CSocketChannel *)sc hadSendBytes:(NSUInteger)bytes
{
    if([_delegate respondsToSelector:@selector(GWService:hadSendBytes:)])
       [_delegate GWService:self hadSendBytes:bytes];
}

//-(int)createLongConnectHTTPChannel:(NSString*)URL
//{
//    int nResult = FALSE;
//    if(_httpchannel == nil)
//    {
//        _httpchannel = [[XMSHttpChannel alloc]initWithURLString:URL];
//        nResult = [CRequestChannelPoolShell addRequestChannel:^CRequestChannel *
//        {
//            return _httpchannel;
//        }];
//        
//        if(nResult==YES)
//        {
//            nResult = [_httpchannel startRequest];
//        }
//    }
//    return nResult;
//}

@end
